﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Globalization;
using Microsoft.Phone.Net.NetworkInformation;
using System.Reflection;
using Microsoft.Phone.Info;
using System.Text;

/// <summary>
/// Namespace containing classes relative to the phone
/// </summary>
namespace BkXitiTagger.Util
{
    /// <summary>
    /// Holds the phone information
    /// </summary>
    public class PhoneInformation
    {
        /// <summary>
        /// Short name of the language parameter
        /// </summary>
        public const string LanguageParameterName = "lng";

        /// <summary>
        /// Short name of the connection type parameter
        /// </summary>
        public const string ConnectionTypeParameterName = "tc";

        /// <summary>
        /// Short name of the operating system parameter
        /// </summary>
        public const string OperationSystemParameterName = "os";

        /// <summary>
        /// Short name of the application version parameter
        /// </summary>
        public const string ApplicationVersionParameterName = "apvr";

        /// <summary>
        /// Short name of the phone model parameter
        /// </summary>
        public const string ModelParameterName = "mdl";

        /// <summary>
        /// Short name of the client identifier parameter
        /// </summary>
        public const string ClientIdentifierParameterName = "idclient";

        private static readonly int ANIDLength = 32;
        private static readonly int ANIDOffset = 2;

        /// <summary>
        /// Keys: description of content
        /// --
        /// lng: language
        /// mdl: model
        /// os: version of the os
        /// tc: connection type (gsm, wifi)
        /// apvr: application version
        /// idclient: unique identifier
        /// </summary>
        public Dictionary<string, string> Information { get; private set; }

        private string CleanString(string str)
        {
            string toRet = str.Replace(" ", "");
            return toRet.ToLower();
        }

        /// <summary>
        /// Get the name of the device manufacturer
        /// </summary>
        /// <returns>The name of the device manufacturer</returns>
        public static string GetManufacturer()
        {
            string result = string.Empty;
            object manufacturer;
            if (DeviceExtendedProperties.TryGetValue("DeviceManufacturer", out manufacturer))
                result = manufacturer.ToString();

            return result;
        }

        /// <summary>
        /// Get the model name of the device
        /// </summary>
        /// <returns>The model name of the device</returns>
        public static string GetDeviceName()
        {
            string result = string.Empty;
            object deviceName;
            if (DeviceExtendedProperties.TryGetValue("DeviceName", out deviceName))
                result = deviceName.ToString();

            return result;
        }

        /// <summary>
        /// Get the raw device unique ID.
        /// Use string representation for statistics with GetDeviceUniqueIDAsString!
        /// </summary>
        /// <returns>A raw  data array containing the devide unique ID</returns>
        /// <remarks>
        /// Note: to get a result requires ID_CAP_IDENTITY_DEVICE  
        /// to be added to the capabilities of the WMAppManifest  
        /// this will then warn users in marketplace
        /// </remarks>
        public static byte[] GetDeviceUniqueID()
        {
            byte[] result = null;
            object uniqueId;
            if (DeviceExtendedProperties.TryGetValue("DeviceUniqueId", out uniqueId))
                result = (byte[])uniqueId;

            return result;
        }

        /// <summary>
        /// Get the string representation of the device unique ID.
        /// </summary>
        /// <returns>Device unique ID in a string</returns>
        public static string GetDeviceUniqueIDAsString()
        {
            StringBuilder sb = new StringBuilder(20);
            byte[] uniqueIdArray = GetDeviceUniqueID();

            foreach (byte b in uniqueIdArray)
            {
                sb.Append((char)(b % 64 + 32));
            }

            return sb.ToString();
        }

        /// <summary>
        /// Get the current user's Windows Live ID.
        /// Can be null if no account has been tied to the phone yet.
        /// </summary>
        /// <returns>The id of the currently configured Windows Live account</returns>
        /// <remarks>
        /// Note: to get a result requires ID_CAP_IDENTITY_USER  
        /// to be added to the capabilities of the WMAppManifest  
        /// this will then warn users in marketplace  
        /// </remarks>
        public static string GetWindowsLiveAnonymousID()
        {
            string result = string.Empty;
            object anid;
            if (UserExtendedProperties.TryGetValue("ANID", out anid))
            {
                if (anid != null && anid.ToString().Length >= (ANIDLength + ANIDOffset))
                {
                    result = anid.ToString().Substring(ANIDOffset, ANIDLength);
                }
            }

            return result;
        } 

        /// <summary>
        /// Get the version number of the current app through the executing assembly's metadata
        /// </summary>
        /// <returns>Version number (without leading "Version=")</returns>
        public string GetAppVersion()
        {
            return Assembly.GetExecutingAssembly().ToString().Split(',')[1].Trim().Replace("Version=", "");
        }

        /// <summary>
        /// Gets the version number of the operating system
        /// </summary>
        /// <returns></returns>
        public string GetOSVersion()
        {
            return string.Format("{0}-{1}.{2}", 
                                    Environment.OSVersion.Platform, 
                                    Environment.OSVersion.Version.Major, 
                                    Environment.OSVersion.Version.Minor);
        }

        /// <summary>
        /// Map containing a set of useful phone information
        /// </summary>
        public PhoneInformation()
        {
            Information = new Dictionary<string, string>();

            // Language
            Information.Add(PhoneInformation.LanguageParameterName, CultureInfo.CurrentCulture.Name);

            // Connection Type
            string connectionType;
            switch (ConnectionInformation.ConnectionType)
            {
                case MobileConnectionType.Wifi:
                    connectionType = "wifi";
                    break;
                case MobileConnectionType.Wwan:
                    connectionType = "gsm";
                    break;
                default:
                    connectionType="unknown";
                    break;
            }
            Information.Add(PhoneInformation.ConnectionTypeParameterName, connectionType);

            // OS version            
            Information.Add(PhoneInformation.OperationSystemParameterName, GetOSVersion());

            // Application version
            // Manipulating string because GetName method is out of reach (security reasons)
            // Assembly.GetCallingAssembly().GetName().Version.ToString()
            Information.Add(PhoneInformation.ApplicationVersionParameterName, GetAppVersion());           

            // Model 
            // TODO: update this with real information about the current phone model and manufacturer
            Information.Add(PhoneInformation.ModelParameterName, GetDeviceName());
            

            // IdClient
            // TODO. update this with real info
            //byte[] buffer = GetDeviceUniqueID();
            //string deviceAsString = System.Text.Encoding.UTF8.GetString(buffer,0, buffer.Length);
            Information.Add(PhoneInformation.ClientIdentifierParameterName, GetDeviceUniqueIDAsString());
        }
    }
}
